package config

import (
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
	"go.uber.org/zap/zapcore"
	"log"
)

var configPath = "/Users/karl/GolandProjects/g_group-buy-market/conf/application.yml"

type Config struct {
	ServiceName string         `mapstruct:"serviceName"` // 服务名称
	Port        string         `mapstruct:"port"`        // 服务端口
	Redis       *RedisConfig   `mapstruct:"redis"`       // redis配置
	ZapLog      *ZapLogConfig  `mapstruct:"zapLog"`      // zap日志配置
	HttpLog     *HttpLogConfig `mapstruct:"httpLog"`     // http请求日志配置
}

// RedisConfig 配置结构体
type RedisConfig struct {
	Addr         string `mapstruct:"addr"`         // redis地址
	Password     string `mapstruct:"password"`     // redis密码
	Database     int    `mapstruct:"database"`     // redis数据库
	PoolSize     int    `mapstruct:"poolSize"`     // 连接池大小
	MinIdleSize  int    `mapstruct:"minIdleSize"`  // 最小空闲连接数
	IdleTimeout  int    `mapstruct:"idleTimeout"`  // 连接超时时间
	ReadTimeout  int    `mapstruct:"readTimeout"`  // 读超时时间
	WriteTimeout int    `mapstruct:"writeTimeout"` // 写超时时间
}

// ZapLogConfig 日志配置结构体
type ZapLogConfig struct {
	LogDir       string        `mapstruct:"logDir"`       // 日志文件目录
	MaxSize      int           `mapstruct:"maxSize"`      // 日志文件最大大小
	MaxBackup    int           `mapstruct:"maxBackUp"`    // 日志文件最大备份数
	MaxAge       int           `mapstruct:"maxAge"`       // 日志文件最大保存时间(天)
	Compress     bool          `mapstruct:"compress"`     // 是否压缩/归档旧日志文件
	HourlyRotate bool          `mapstruct:"hourlyRotate"` // 每小时切割日志文件
	LogLevel     zapcore.Level `mapstruct:"logLevel"`     // 日志级别
}

// HttpLogConfig http请求日志配置结构体
type HttpLogConfig struct {
	LogRequestBody    bool     `mapstruct:"logRequestBody"`    // 是否记录请求体
	LogResponseBody   bool     `mapstruct:"logResponseBody"`   // 是否记录响应体
	ExcludePaths      []string `mapstruct:"excludePaths"`      // 排除的路径
	ExcludeReqHeaders []string `mapstruct:"excludeReqHeaders"` // 排除的请求头
	ExcludeResHeaders []string `mapstruct:"excludeResHeaders"` // 排除的响应头
	SensitiveFields   []string `mapstruct:"sensitiveFields"`   // 敏感字段
}

func LoadConfig() (*Config, error) {
	// 设置配置文件路径
	viper.SetConfigFile(configPath)

	// 初始读取配置文件
	if err := viper.ReadInConfig(); err != nil {
		log.Fatalf("Error reading config file: %v", err)
	}

	var config Config

	// 正确：直接传入指针，不需要
	if err := viper.Unmarshal(&config); err != nil {
		log.Fatalf("Error unmarshaling config: %v", err)
	}
	// 设置配置文件监听
	viper.WatchConfig()

	// 配置文件变化回调函数
	viper.OnConfigChange(func(e fsnotify.Event) {
		log.Printf("Config file changed: %s", e.Name)

		// 重新读取配置文件
		if err := viper.ReadInConfig(); err != nil {
			log.Printf("Error re-reading config: %v", err)
			return
		}

		// 重新解析配置
		if err := viper.Unmarshal(&config); err != nil {
			log.Printf("Error re-unmarshaling config: %v", err)
			return
		}

		log.Printf("Config reloaded successfully: %+v", config)
	})

	log.Println("Config file watcher started")

	return &config, nil
}
